package indexer;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Logger;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.KeywordAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class Searcher {

    /**
     * Current Prototype
     *  edit @07:35AM\
     * @param args no args
     */
	private static final Logger log = Logger.getLogger(Searcher.class.getName());
	public static void main(String[] args) {
		try {

			String index_location = System.getProperty("index");

			Directory fdr = FSDirectory.open(new File(index_location));

			IndexReader reader = IndexReader.open(fdr, true);

			IndexSearcher indexSearcher = new IndexSearcher(reader);

			String requestItem = "Method_println";
			String packageContext = "scb";
			String len = "0";

			if (!len.matches("\\d+"))
				return;

			ScoreDoc[] hits = QueryForMethodByName_len(indexSearcher,
					requestItem, packageContext, 1);

			List<HashMap<String, String>> results = parseHits(indexSearcher,
					hits, requestItem);

			StringBuffer sb = new StringBuffer();
			if (results == null)
				return;
			ParseQueryToJson(results, sb);

			log.info(sb.toString());
		} catch (IOException e) {

			e.printStackTrace();
		}

	}

    private static void ParseQueryToJson(List<HashMap<String, String>> results, StringBuffer sb) {
        sb.append("function byName(){");
        long i = 0;
        for (HashMap<String, String> hm : results) {
            sb.append("\nthis.Caller[" + i + "]:").append(hm.get("Caller"));
            sb.append(";this.Line[" + i + "]:").append(hm.get("Line"));
            sb.append(";this.Scope[" + i + "]:").append(hm.get("Scope"));
            sb.append(";this.Args[" + i + "]:").append(hm.get("Args"));
            sb.append(";this.Doc[" + i + "]:").append(hm.get("Doc"));
            sb.append(";thisLength[" + (i++) + "]:").append(hm.get("Length"));
        }

        sb.append("\nthis.api=0.3;}");
    }

    private static ScoreDoc[] QueryForMethodByName(IndexSearcher indexSearcher, String requestItem, String packageContext) throws IOException {
        Term term = new Term(requestItem, packageContext + ".*".toLowerCase());

        Query termQuery = new WildcardQuery(term);
        Analyzer ana = new KeywordAnalyzer();
        TopScoreDocCollector collector = TopScoreDocCollector.create(100, true);
        indexSearcher.search(termQuery, collector);
        return collector.topDocs().scoreDocs;
    }

    private static ScoreDoc[] QueryForMethodByName_len(IndexSearcher indexSearcher, String requestItem, String packageContext, int len) throws IOException {
        Term term = new Term(requestItem, packageContext + ".*".toLowerCase());
        Term term2 = new Term(requestItem + "_len", Integer.toString(len));
        BooleanQuery boolQry = new BooleanQuery();
        Query lenQuery = new TermQuery(term2);
        Query termQuery = new WildcardQuery(term);
        boolQry.add(lenQuery, BooleanClause.Occur.MUST);
        boolQry.add(termQuery, BooleanClause.Occur.SHOULD);

        Analyzer ana = new KeywordAnalyzer();
        TopScoreDocCollector collector = TopScoreDocCollector.create(100, true);
        indexSearcher.search(boolQry, collector);
        return collector.topDocs().scoreDocs;
    }

    private static List<HashMap<String, String>> parseHits(IndexSearcher indexSearcher, ScoreDoc[] hits, String name) throws IOException {
        List<HashMap<String, String>> answer = new ArrayList<HashMap<String, String>>();
        HashMap<String, String> hm = null;
        HashMap<Integer, Document> ha = null;

        ha = new HashMap<Integer, Document>();
        log.info(Integer.toString(hits.length));
        for (ScoreDoc hit : hits) {
            ha.put(Integer.valueOf(hit.doc), indexSearcher.doc(hit.doc));
        }
        log.info(Integer.toString(ha.size()));
        for (Integer in : ha.keySet()) {
            Document doc = ha.get(in);

            hm = new HashMap<String, String>();

            hm.put("Caller", doc.get(name));
            hm.put("Line", doc.get(name + "_start"));
            hm.put("Scope", doc.get(name + "_scope"));
            hm.put("Length", doc.get(name + "_len"));
            hm.put("Args", doc.get(name + "_args"));
            hm.put("Doc", in.toString());
            answer.add(hm);


        }
        return answer;
    }

}
